package com.example.multi.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.example.multi.config.Config;
import com.example.multi.config.ExecutorConstant;
import com.example.multi.entity.Order;
import com.example.multi.entity.Resp;
import com.example.multi.entity.User;
import com.example.multi.service.IOrderService;
import com.example.multi.service.IUserService;
import com.example.multi.util.WebUtil;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;

@Slf4j
@Service
public class OrderService implements IOrderService {

    /**
     * 获取订单code列表
     * @return
     */
    @Override
    public List<String> listOrderCode(){
        //使用httpUtil 模拟 feign请求服务接口 start
        String reqUrl = Config.baseUrl.concat("/v1/order/list");
        HttpRequest httpRequest = HttpUtil.createGet(reqUrl);
        //设置请求头信息
        String token = WebUtil.getCurrentRequestHeaderToken();
        httpRequest.header("token",token);
        HttpResponse httpResponse = httpRequest.execute();

        String body = httpResponse.body();
        Resp<List<String>> respData = JSONUtil.toBean(body, Resp.class);
        //使用httpUtil 模拟 feign请求服务接口 end

        if(respData.isSuccess()){
            return respData.getData();
        }
        return null;
    };

    /**
     * 根据订单code获取 订单数据
     * @param orderCode
     * @return
     */
    @Override
    public Order getOrder(String orderCode){

        //使用httpUtil 模拟 feign请求服务接口 start
        String reqUrl = StrUtil.format(Config.baseUrl.concat("/v1/order/get?orderCode={}"),orderCode);
        HttpRequest httpRequest = HttpUtil.createGet(reqUrl);
        //设置请求头信息
        String token = WebUtil.getCurrentRequestHeaderToken();
        httpRequest.header("token",token);
        HttpResponse httpResponse = httpRequest.execute();

        String body = httpResponse.body();
        Gson gson = new Gson();
        Resp<Order> respData = gson.fromJson(body , new TypeToken<Resp<Order>>(){}.getType());
        //使用httpUtil 模拟 feign请求服务接口 end
        if(respData.isSuccess()){
            return respData.getData();
        }
        return null;
    };


    /**
     * 获取订单列表（串行获取）
     * @return
     */
    @Override
    public List<Order> listOrder_1(){
        //获取订单列表 start
        List<Order> orderList = new ArrayList<>();

        List<String> orderCodes = listOrderCode();
        orderCodes.stream().forEach(orderCode->{
            Order order = getOrder(orderCode);
            orderList.add(order);
        });
        //获取订单列表 end
        return orderList;
    };

    /**
     * 获取订单列表（并行获取数据）
     * stream也改成了parallelStream 并行for循环
     * @return
     */
    @Async
    @Override
    public Future<List<Order>> listOrder_2(){
        log.info("listOrder_2 当前线程是：{}",Thread.currentThread().getName());
        //获取订单列表 start
        List<Order> orderList = new ArrayList<>();

        List<String> orderCodes = listOrderCode();
        if(CollUtil.isNotEmpty(orderCodes)){
            orderCodes.parallelStream().forEach(orderCode->{
                Order order = getOrder(orderCode);
                if(order!=null){
                    orderList.add(order);
                }
            });
        }
        //获取订单列表 end
        return new AsyncResult<List<Order>>(orderList);
    };


    /**
     * 获取订单列表（并行获取数据）(把主线程的request的数据 透传给 子线程和子子线程)
     * @return
     */
    @Override
    public List<Order> listOrder_3(){
        //获取订单列表 start
        List<Order> orderList = new ArrayList<>();

        List<String> orderCodes = listOrderCode();
        if(CollUtil.isNotEmpty(orderCodes)){
            RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
            orderCodes.parallelStream().forEach(orderCode->{
                RequestContextHolder.setRequestAttributes(attributes);
                try {
                    Order order = getOrder(orderCode);
                    if(order!=null){
                        orderList.add(order);
                    }
                }finally {
                    RequestContextHolder.resetRequestAttributes();
                }
            });
        }
        //获取订单列表 end
        return orderList;
    };


    /**
     * 获取订单列表（并行获取数据）
     * stream也改成了parallelStream 并行for循环
     * @return
     */
    @Async(ExecutorConstant.simpleExecutor_4)
    @Override
    public Future<List<Order>> listOrder_4(){
        log.info("listOrder_4 当前线程是：{}",Thread.currentThread().getName());
        //获取订单列表 start
        List<Order> orderList = new ArrayList<>();

        List<String> orderCodes = listOrderCode();
        if(CollUtil.isNotEmpty(orderCodes)){
            orderCodes.parallelStream().forEach(orderCode->{
                Order order = getOrder(orderCode);
                if(order!=null){
                    orderList.add(order);
                }
            });
        }
        //获取订单列表 end
        return new AsyncResult<List<Order>>(orderList);
    };
}
